<template>
  <div class="widget-form-container">
    <div v-if="data.list.length == 0" class="form-empty">
      {{ $t('fm.description.containerEmpty') }}
    </div>
    <el-form
      class="canvas_form"
      :size="data.config.size"
      label-suffix=":"
      :label-position="data.config.labelPosition"
      :label-width="data.config.labelWidth + 'px'"
    >
      <draggable
        class=""
        v-model="data.list"
        v-bind="{
          group: 'widgets',
          ghostClass: 'ghost',
          animation: 200,
          handle: '.drag-widget',
        }"
        @end="handleMoveEnd"
        @move="checkMove"
        @add="handleWidgetAdd"
      >
        <transition-group name="fade" tag="div" class="widget-form-list">
          <template v-for="(element, index) in data.list">
            <template v-if="element.type == 'grid'">
              <el-row
                class="widget-col widget-view"
                v-if="element && element.key"
                :key="element.key"
                type="flex"
                :class="{ active: selectWidget.key == element.key }"
                :gutter="element.options.gutter ? element.options.gutter : 0"
                :justify="element.options.justify"
                :align="element.options.align"
                @click.native="handleSelectWidget(index)"
              >
                <el-col
                  v-for="(col, colIndex) in element.columns"
                  :key="colIndex"
                  :span="col.span ? col.span : 0"
                >
                  <draggable
                    v-model="col.list"
                    :no-transition-on-drag="true"
                    v-bind="{
                      group: 'widgets',
                      ghostClass: 'ghost',
                      animation: 200,
                      handle: '.drag-widget',
                    }"
                    @end="handleMoveEnd"
                    @add="handleWidgetColAdd($event, element, colIndex)"
                  >
                    <transition-group
                      name="fade"
                      tag="div"
                      class="widget-col-list"
                    >
                      <template v-for="(el, i) in col.list">
                        <widget-form-flex-container
                          v-if="el.key && element.type == 'flexContainer'"
                          :key="el.key"
                          :element="el"
                          :select.sync="selectWidget"
                          :index="index"
                          :data="data"
                          :remote="remote"
                        />
                        <widget-form-item
                          :key="el.key"
                          v-else-if="el.key"
                          :element="el"
                          :select.sync="selectWidget"
                          :index="i"
                          :data="col"
                          :remote="remote"
                        >
                        </widget-form-item>
                      </template>
                    </transition-group>
                  </draggable>
                </el-col>
                <div
                  class="widget-view-action widget-col-action"
                  v-if="selectWidget.key == element.key"
                >
                  <i
                    class="iconfont icon-trash"
                    @click.stop="handleWidgetDelete(index)"
                  ></i>
                </div>

                <div
                  class="widget-view-drag widget-col-drag"
                  v-if="selectWidget.key == element.key"
                >
                  <i class="iconfont icon-drag drag-widget"></i>
                </div>
              </el-row>
            </template>
            <template v-else-if="element.type == 'group'">
              <widget-form-group
                v-if="element && element.key"
                :key="element.key"
                :element="element"
                :select.sync="selectWidget"
                :index="index"
                :data="data"
                :remote="remote"
              />
            </template>
            <template v-else-if="element.type == 'tabs'">
              <widget-form-tabs-item
                v-if="element && element.key"
                :select.sync="selectWidget"
                :element="element"
                :key="element.key"
                :index="index"
                :data="data"
                :remote="remote"
              />
            </template>
            <template v-else-if="element.type == 'flexContainer'">
              <widget-form-flex-container
                v-if="element && element.key"
                :key="element.key"
                :element="element"
                :select.sync="selectWidget"
                :index="index"
                :data="data"
                :remote="remote"
              />
            </template>
            <template v-else>
              <widget-form-item
                v-if="element && element.key"
                :key="element.key"
                :element="element"
                :select.sync="selectWidget"
                :index="index"
                :data="data"
                :remote="remote"
              />
            </template>
          </template>
        </transition-group>
      </draggable>
    </el-form>
  </div>
</template>

<script>
import Draggable from 'vuedraggable'
import WidgetFormItem from './WidgetFormItem'
import WidgetFormTabsItem from './WidgetFormTabsItem.vue'
import WidgetFormFlexContainer from './WidgetFormFlexContainer.vue'
import WidgetFormGroup from './WidgetFormGroup.vue'

export default {
  components: {
    Draggable,
    WidgetFormItem,
    WidgetFormTabsItem,
    WidgetFormFlexContainer,
    WidgetFormGroup,
  },
  props: ['data', 'select', 'remote'],
  data() {
    return {
      selectWidget: this.select,
    }
  },
  mounted() {
    document.body.ondrop = function (event) {
      let isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1
      if (isFirefox) {
        event.preventDefault()
        event.stopPropagation()
      }
    }
  },
  methods: {
    handleMoveEnd({ newIndex, oldIndex }) {
      console.log('index', newIndex, oldIndex)
    },
    handleSelectWidget(index) {
      console.log(index, '#####')
      this.selectWidget = this.data.list[index]
    },
    handleWidgetAdd(evt) {
      const newIndex = evt.newIndex
      const oldIndex = evt.oldIndex
      const to = evt.to
      //为拖拽到容器的元素添加唯一 key
      const key =
        Date.parse(new Date()) + '_' + Math.ceil(Math.random() * 99999)
      let tmp = {
        ...this.data.list[newIndex],
        options: {
          ...this.data.list[newIndex].options,
          remoteFunc: 'func_' + key,
        },
        key,
        // 绑定键值
        model: this.data.list[newIndex].type + '_' + key,
        rules: [],
      }

      if (
        this.data.list[newIndex].type === 'radio' ||
        this.data.list[newIndex].type === 'checkbox' ||
        this.data.list[newIndex].type === 'select' ||
        this.data.list[newIndex].type === 'refusecode'
      ) {
        tmp = {
          ...tmp,
          options: {
            ...tmp.options,
            options: tmp.options.options.map((item) => ({
              ...item,
            })),
          },
        }
      }

      if (
        this.data.list[newIndex].type === 'grid' ||
        this.data.list[newIndex].type === 'flexContainer'
      ) {
        const columns = this.data.list[newIndex].columns || []
        tmp = {
          ...tmp,
          columns: columns.map((item) => ({
            ...item,
          })),
        }
      }

      if (this.data.list[newIndex].type === 'tabs') {
        const tabs = this.data.list[newIndex].tabs || []
        tmp = {
          ...tmp,
          tabs: tabs.map((item) => ({
            ...item,
            list: [],
          })),
        }
      }

      if (this.data.list[newIndex].type === 'form') {
        const preWidgets = JSON.parse(
          JSON.stringify(this.data.list.slice(0, newIndex))
        )
        const sufWidgets = JSON.parse(
          JSON.stringify(this.data.list.slice(newIndex + 1))
        )

        tmp.form.list.forEach((formItem) => {
          const widget = this.generateWidget(formItem)
          preWidgets.push(widget)
        })
        this.$set(this.data, 'list', [...preWidgets, ...sufWidgets])
      } else {
        this.$set(this.data.list, newIndex, tmp)
      }
      this.selectWidget = this.data.list[newIndex]
    },
    handleWidgetColAdd($event, row, colIndex) {
      console.log('coladd', $event, row, colIndex)
      const newIndex = $event.newIndex
      const oldIndex = $event.oldIndex
      const item = $event.item

      // 防止布局元素的嵌套拖拽
      if (item.className.indexOf('data-grid') >= 0) {
        // 如果是列表中拖拽的元素需要还原到原来位置
        item.tagName === 'DIV' &&
          this.data.list.splice(
            oldIndex,
            0,
            row.columns[colIndex].list[newIndex]
          )

        row.columns[colIndex].list.splice(newIndex, 1)

        return false
      }

      console.log('from', item)

      const key =
        Date.parse(new Date()) + '_' + Math.ceil(Math.random() * 99999)

      this.$set(row.columns[colIndex].list, newIndex, {
        ...row.columns[colIndex].list[newIndex],
        options: {
          ...row.columns[colIndex].list[newIndex].options,
          remoteFunc: 'func_' + key,
        },
        key,
        // 绑定键值
        model: row.columns[colIndex].list[newIndex].type + '_' + key,
        rules: [],
      })

      if (
        row.columns[colIndex].list[newIndex].type === 'radio' ||
        row.columns[colIndex].list[newIndex].type === 'checkbox' ||
        row.columns[colIndex].list[newIndex].type === 'select' ||
        row.columns[colIndex].list[newIndex].type === 'refusecode'
      ) {
        this.$set(row.columns[colIndex].list, newIndex, {
          ...row.columns[colIndex].list[newIndex],
          options: {
            ...row.columns[colIndex].list[newIndex].options,
            options: row.columns[colIndex].list[newIndex].options.options.map(
              (item) => ({
                ...item,
              })
            ),
          },
        })
      }

      this.selectWidget = row.columns[colIndex].list[newIndex]
    },
    handleWidgetDelete(index) {
      if (this.data.list.length - 1 === index) {
        if (index === 0) {
          this.selectWidget = {}
        } else {
          this.selectWidget = this.data.list[index - 1]
        }
      } else {
        this.selectWidget = this.data.list[index + 1]
      }

      this.$nextTick(() => {
        this.data.list.splice(index, 1)
      })
    },
    generateWidget(widget) {
      let tmp = JSON.parse(JSON.stringify(widget))
      console.log('generate widget =========================')
      console.log(widget)
      console.log('=========================')
      const key =
        Date.parse(new Date()) + '_' + Math.ceil(Math.random() * 99999)
      tmp = {
        ...tmp,
        key,
        model: `${tmp.type}_${key}`,
      }
      if (widget.type === 'tabs') {
        const tabs = tmp.tabs.map((item) => {
          const list = item.list.map((subItem) => {
            return this.generateWidget(subItem)
          })
          return {
            ...item,
            list,
          }
        })
        tmp.tabs = tabs
      } else if (widget.type === 'grid' || widget.type === 'flexContainer') {
        const columns = tmp.columns.map((item) => {
          const list = item.list.map((subItem) => {
            return this.generateWidget(subItem)
          })
          return {
            ...item,
            list,
          }
        })
        tmp.columns = columns
      }
      // const noModelLabels = ['blank', 'grid', 'tabs', 'flexContainer']
      return tmp
    },
    checkMove(evt) {
      console.log('check move =================')
      console.log(evt)
      console.log('=================')
      return true
    },
  },
  watch: {
    data: {
      deep: true,
      handler(val) {
        console.log('\n\n------ begin: widget form data change ------')
        console.log(val)
        console.log('------ end: widget form data change ------\n\n')
      },
    },
    select(val) {
      this.selectWidget = val
    },
    selectWidget: {
      handler(val) {
        this.$emit('update:select', val)
      },
      deep: true,
    },
  },
}
</script>

<style lang="scss" scoped>
.canvas_form {
  margin: 0;
  padding: 0;
  width: 100%;
  min-height: 100%;
  box-sizing: border-box;
  & > div {
    height: 100%;
  }
}
.widget-form-list {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
}
</style>
